﻿using SCG.Prism.Server;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using SCG.Prism;
using System.Net;
using System.Timers;

namespace SCGMasterServer
{
    public partial class SCGMasterServer : ServiceBase
    {
        //constructor
        public SCGMasterServer()
        {
            InitializeComponent();

            //create the PrismServer component and make it use XML storage for user info
            _prism = new PrismServer();
            _prism.BasePath = ConfigurationManager.AppSettings["PrismPath"];
            if (!Directory.Exists(_prism.BasePath))
                Directory.CreateDirectory(_prism.BasePath);
            XmlStorage xml = new XmlStorage();
            _prism.Storage = xml;

            //custom command modules
            SVCommandModule svc = new SVCommandModule();
            _prism.InstallCommandModule(svc);

            //set server properties, read port from config file
            _prism.Port = Int32.Parse(ConfigurationManager.AppSettings["Port"]);
            _prism.ProhibitSameIP = ConfigurationManager.AppSettings["BlockDuplicateIP"].ToUpper() == "YES";
            _prism.ProhibitSameUserName = true;

            //hook event handlers
            _prism.GuestConnected += _prism_GuestConnected;
            _prism.GuestDisconnected += _prism_GuestDisconnected;
            _prism.GuestDisconnectedSameIP += _prism_GuestDisconnectedSameIP;
            _prism.ExceptionOcurred += _prism_ExceptionOcurred;
            _prism.GuestLoggedIn += _prism_GuestLoggedIn;
            _prism.RoomAdded += _prism_RoomAdded;
            _prism.RoomRemoved += _prism_RoomRemoved;

            //determine my IP
            try
            {
                WebRequest request = WebRequest.Create("http://www.siliconcommandergames.com/asp/IP.aspx");
                WebResponse response = request.GetResponse();
                Stream s = response.GetResponseStream();
                StreamReader sr = new StreamReader(s);
                string content = sr.ReadToEnd();
                sr.Close();
                response.Close();
                int pos = content.IndexOf("lblIP\">");
                content = content.Substring(pos + 7);
                pos = content.IndexOf("<");
                _myIP = content.Substring(0, pos);
                Log("My IP is: " + _myIP);

                //send an FTP to SCG to let the world know about this server!
                if (_myIP != "")
                {
                    PingSCG();

                    //set up timer to notify SCG every day that we are running
                    Timer t = new Timer();
                    t.Interval = 1000 * 60 * 60 * 24;
                    t.Elapsed += new ElapsedEventHandler(OnTimer);
                    t.Start();
                }
            }
            catch (Exception ex)
            {
                Log("Error determining my IP: " + ex.Message);
            }
        }

        //room removed
        void _prism_RoomRemoved(object sender, PrismRoomEventArgs e)
        {
            string s = "Room Removed: " + e.Room.RoomName;
            Log(s);
        }

        //room added
        void _prism_RoomAdded(object sender, PrismRoomEventArgs e)
        {
            string s = "Room Added: " + e.Room.RoomName;
            Log(s);
        }

        //guest logged in
        void _prism_GuestLoggedIn(object sender, PrismGuestEventArgs e)
        {
            string s = "Guest Logged in: " + e.Guest;
            Log(s);
        }

        //exception
        void _prism_ExceptionOcurred(object sender, ExceptionEventArgs e)
        {
            string s = "Exception: " + e.Exception.Message;
            Log(s);
        }

        //guest forced off
        void _prism_GuestDisconnectedSameIP(object sender, PrismGuestEventArgs e)
        {
            string s = "Duplicate IP, Guest Disconnected: " + e.Guest;
            Log(s);
        }

        //guest disconnected
        void _prism_GuestDisconnected(object sender, PrismGuestEventArgs e)
        {
            string s = "Guest Disconnected: " + e.Guest;
            Log(s);
        }

        //Guest connected
        void _prism_GuestConnected(object sender, PrismGuestEventArgs e)
        {
            string s = "Guest Connected: " + e.Guest;
            Log(s);
        }

        //start the server
        protected override void OnStart(string[] args)
        {
            try
            {
                _prism.Active = true;
                Log("Server Started, listening on Port " + _prism.Port);
            }
            catch (Exception ex)
            {
                Log("Exception in Server Start: " + ex.Message);
            }
        }

        //stop the server
        protected override void OnStop()
        {
            if (_prism.Active)
            {
                _prism.Active = false;
                Log("Server Stopped");
            }
        }

        //private members
        private PrismServer _prism;
        private string _myIP = "";

        //add an item to the log file
        private static object _fileLock = new object();
        private void Log(string s)
        {
            string fileName = _prism.BasePath + @"\Log" + DateTime.Now.Date.ToString("yyyy-MM-dd") + ".txt";
            s = DateTime.Now + ": " + s;
            lock (_fileLock)
            {
                if (File.Exists(fileName))
                {
                    using (StreamWriter writer = File.AppendText(fileName))
                    {
                        writer.WriteLine(s);
                        writer.Close();
                    }
                }
                else
                {
                    File.WriteAllText(fileName, s + Environment.NewLine);
                }
            }
        }

        //timer to notify SCG every day that this server is running
        private void OnTimer(object source, ElapsedEventArgs e)
        {
            PingSCG();
        }
        private void PingSCG()
        {
            try
            {
                Log("Pinging SCG!");
                FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create("ftp://ftp.siliconcommandergames.com/PrismServers/" + _myIP + ".txt");
                ftp.Credentials = new NetworkCredential("PrismServer", "s1licon_commander");
                ftp.Method = WebRequestMethods.Ftp.UploadFile;
                Stream s = ftp.GetRequestStream();
                string machineName = Environment.MachineName;
                byte[] buffer = new byte[machineName.Length];
                for (int n = 0; n < machineName.Length; n++)
                    buffer[n] = (byte)machineName[n];
                s.Write(buffer, 0, machineName.Length);
                s.Close();
                ftp = null;
            }
            catch (Exception ex)
            {
                Log("Error sending IP file: " + ex.Message);
            }
        }
    }
}
